package com.exonline.controller.courses;

import cn.hutool.core.util.IdUtil;

import com.exonline.base.IBaseServlet;
import com.exonline.commons.utils.QiNiuUploadUtils;
import com.exonline.commons.utils.TokenUtil;
import com.exonline.entity.Courses;
import com.exonline.entity.Direction;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * @desc : 课程管理 的C层
 * @author : JJR
 */

@WebServlet("/font/courses")
public class CoursesServlet  extends HttpServlet implements IBaseServlet {
    ObjectMapper mapper = new ObjectMapper();
    CoursesService service = new CoursesService();
    static QiNiuUploadUtils qiNiuUploadUtils = new QiNiuUploadUtils();

    // 上传配置
    private static final int MEMORY_THRESHOLD   = 1024 * 1024 * 3;  // 3MB
    private static final int MAX_FILE_SIZE      = 1024 * 1024 * 40; // 40MB
    private static final int MAX_REQUEST_SIZE   = 1024 * 1024 * 1024 ; // 50MB

    int pageno = 1;
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         String method = req.getParameter("method");
         if (req.getParameter("pageno") != null){
             pageno = Integer.parseInt(req.getParameter("pageno"));
         }
                 try {
                     //直接查课程,返回课程列表
                     if ("queryall".equals(method)) {
                         this.query(req, resp);
                     } else if("structurequery".equals(method)){
                         this.structurequery(req,resp);
                     } else if ("queryone".equals(method)) {
                         this.queryOne(req, resp);
                     } else if ("add".equals(method)) {
                         this.add(req, resp);
                     } else if ("edit".equals(method)) {
                         this.edit(req, resp);
                     } else if ("delete".equals(method)) {
                         this.delete(req, resp);
                     } else if ("tquery".equals(method)) {
                         this.tquery(req,resp);
                     } else if ("leaderboard".equals(method)) {
                         this.leaderboard(req,resp);
                     } else if ("individualcoursequery".equals(method)) {
                         this.individualcoursequery(req,resp);
                     } else if ("newcouarsequery".equals(method)) {
                         this.newcouarsequery(req,resp);
                     } else if ("addcollect".equals(method)){
                         this.addcollect(req,resp);
                     } else if ("collect".equals(method)) {
                         this.collect(req,resp);
                     } else if ("search".equals(method)) {
                         this.search(req,resp);
                     }
                 } catch (Exception e) {
                     throw new ServletException(e);
                 };
    }

    /**
     * @desc  根据课程名称进行模糊查询
     * @param req
     * @param resp
     */
    private void search(HttpServletRequest req, HttpServletResponse resp) {
        try {
            // 获取前端传递的课程名参数，假设参数名为 "courseName"，可根据实际调整
            String courseName = req.getParameter("courseName");
            if (courseName == null || courseName.trim().isEmpty()) {
                Map<String, Object> map = new HashMap<>();
                map.put("code", 400);
                map.put("msg", "请输入有效的课程名进行查询");
                map.put("data", null);
                mapper.writeValue(resp.getWriter(), map);
                return;
            }

            // 获取Service实例（这里假设已经在类中正确初始化了service对象）
            CoursesService service = new CoursesService();

            // 调用Service层的方法进行模糊查询
            List<Courses> courses = service.searchCoursesByName(courseName);

            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("code", 200);
            resultMap.put("msg", "课程名模糊查询成功");
            resultMap.put("data", courses);

            // 将查询结果转换为JSON格式并写入响应
            mapper.writeValue(resp.getWriter(), resultMap);
        } catch (IOException e) {
            e.printStackTrace();
            try {
                Map<String, Object> errorMap = new HashMap<>();
                errorMap.put("code", 500);
                errorMap.put("msg", "课程名模糊查询过程中出现错误");
                errorMap.put("data", null);
                mapper.writeValue(resp.getWriter(), errorMap);
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

    /**
     * @desc  课程添加到收藏表
     * @param req
     * @param resp
     */
    private void addcollect(HttpServletRequest req, HttpServletResponse resp) {
        try {
            // 从Session中获取学生id
            String studentId = TokenUtil.getId(req);

            // 检查是否成功从Session获取到学生id，如果未获取到，返回错误信息
            if (studentId == null) {
                Map<String, Object> map = new HashMap<>();
                map.put("code", 201);
                map.put("msg", "未能从Session中获取到学生id，请检查相关设置");
                map.put("data", null);
                mapper.writeValue(resp.getWriter(), map);
                return;
            }

            // 获取要收藏的课程id，假设前端传递课程id的参数名为"courseId"，你可根据实际情况调整
            String courseId = req.getParameter("courseId");
            if (courseId == null) {
                Map<String, Object> map = new HashMap<>();
                map.put("code", 400);
                map.put("msg", "未获取到要收藏的课程id，请检查前端参数传递");
                map.put("data", null);
                mapper.writeValue(resp.getWriter(), map);
                return;
            }

            // 获取Service实例（这里假设已经在类中正确初始化了service对象）
            CoursesService service = new CoursesService();

            // 调用Service层方法将课程添加到收藏表中
            boolean result = service.addCourseToCollection(studentId, courseId);
            Map<String, Object> resultMap = new HashMap<>();
            if (result) {
                resultMap.put("code", 200);
                resultMap.put("msg", "课程添加到收藏表成功");
            } else {
                resultMap.put("code", 500);
                resultMap.put("msg", "课程添加到收藏表失败，请检查数据库相关配置或数据是否合法");
            }
            resultMap.put("data", null);

            // 将操作结果转换为JSON格式并写入响应
            mapper.writeValue(resp.getWriter(), resultMap);
        } catch (IOException e) {
            e.printStackTrace();
            try {
                Map<String, Object> errorMap = new HashMap<>();
                errorMap.put("code", 500);
                errorMap.put("msg", "将课程添加到收藏表过程中出现错误");
                errorMap.put("data", null);
                mapper.writeValue(resp.getWriter(), errorMap);
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

    /**
     * @desc  个人中心 收藏课程查询
     * @param req
     * @param resp
     */
    private void collect(HttpServletRequest req, HttpServletResponse resp) {
        try {
            // 从Session中获取学生id
            String studentId = TokenUtil.getId(req);

            // 检查是否成功从Session获取到学生id，如果未获取到，返回错误信息
            if (studentId == null) {
                Map<String, Object> map = new HashMap<>();
                map.put("code", 201);
                map.put("msg", "未能从Session中获取到学生id，请检查相关设置");
                map.put("data", null);
                mapper.writeValue(resp.getWriter(), map);
                return;
            }

            // 获取Service实例（这里假设已经在类中正确初始化了service对象）
            CoursesService service = new CoursesService();

            // 调用Service层方法获取该学生收藏的课程信息列表（以Map形式表示每条课程记录）
            List<Map<String, Object>> collectedCourses = service.getCollectedCourses(studentId);
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("code", 200);
            resultMap.put("msg", "收藏课程查询成功");
            resultMap.put("data", collectedCourses);

            // 将收藏课程信息列表转换为JSON格式并写入响应
            mapper.writeValue(resp.getWriter(), resultMap);
        } catch (IOException e) {
            e.printStackTrace();
            try {
                Map<String, Object> errorMap = new HashMap<>();
                errorMap.put("code", 500);
                errorMap.put("msg", "收藏课程查询过程中出现错误");
                errorMap.put("data", null);
                mapper.writeValue(resp.getWriter(), errorMap);
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

    /**
     * @desc  新课推荐的查询
     * @param req
     * @param resp
     */
    private void newcouarsequery(HttpServletRequest req, HttpServletResponse resp) {
        try {
            // 获取Service实例（这里假设已经在类中正确初始化了service对象）
            CoursesService service = new CoursesService();

            // 调用Service层方法获取新课推荐课程信息列表（以Map形式表示每条课程记录）
            List<Direction> newCourses = service.getNewCourses();
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("code", 200);
            resultMap.put("msg", "新课推荐查询成功");
            resultMap.put("data", newCourses);

            // 将新课推荐课程信息列表转换为JSON格式并写入响应
            mapper.writeValue(resp.getWriter(), resultMap);
        } catch (IOException | SQLException e) {
            e.printStackTrace();
            try {
                Map<String, Object> errorMap = new HashMap<>();
                errorMap.put("code", 500);
                errorMap.put("msg", "新课推荐查询过程中出现错误");
                errorMap.put("data", null);
                mapper.writeValue(resp.getWriter(), errorMap);
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }

    }

    /**
     * @desc  个人中心的学习记录查询
     * @param req
     * @param resp
     */
    private void individualcoursequery(HttpServletRequest req, HttpServletResponse resp) {
        try {
             String studentId = TokenUtil.getId(req);

            // 检查是否成功从Session获取到学生id，如果未获取到，返回错误信息
            if (studentId == null) {
                Map<String, Object> map = new HashMap<>();
                map.put("code", 201);
                map.put("msg", "未能从Session中获取到学生id，请检查相关设置");
                map.put("data", null);
                mapper.writeValue(resp.getWriter(), map);
                return;
            }

            // 获取Service实例（这里假设已经在类中正确初始化了service对象）
            CoursesService service = new CoursesService();

            // 根据学生id获取该学生学习的课程信息列表（以Map形式表示每条课程记录）
            List<Map<String, Object>> courses = service.getIndividualCourses(studentId);
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("code", 200);
            resultMap.put("msg", "查询学生个人学习课程成功");
            resultMap.put("data", courses);

            // 将课程信息列表转换为JSON格式并写入响应
            mapper.writeValue(resp.getWriter(), resultMap);
        } catch (IOException | SQLException e) {
            e.printStackTrace();
            try {
                Map<String, Object> errorMap = new HashMap<>();
                errorMap.put("code", 500);
                errorMap.put("msg", "查询学生个人学习课程过程中出现错误");
                errorMap.put("data", null);
                mapper.writeValue(resp.getWriter(), errorMap);
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }

    }

    /**
     * @desc  排行榜查询
     * @param req
     * @param resp
     */
    private void leaderboard(HttpServletRequest req, HttpServletResponse resp) {
        try {
            // 获取请求中的榜单类型参数（假设名为 boardType）
            String boardType = req.getParameter("boardType");

            // 获取Service实例（这里假设已经在类中正确初始化了service对象）
            CoursesService service = new CoursesService();

            // 根据榜单类型获取相应榜单数据
            List<Map<String, Object>> boardData = service.getBoardData(boardType);
            Map<String, Object> resultMap = new HashMap<>();
            if ("best_selling".equals(boardType)) {
                resultMap.put("code", 200);
                resultMap.put("msg", "畅销榜查询成功");
            } else if ("most_studied".equals(boardType)) {
                resultMap.put("code", 200);
                resultMap.put("msg", "学习榜查询成功");
            } else {
                resultMap.put("code", 400);
                resultMap.put("msg", "无效的榜单类型参数");
                mapper.writeValue(resp.getWriter(), resultMap);
                return;
            }
            resultMap.put("data", boardData);

            // 将榜单数据转换为JSON格式并写入响应
            mapper.writeValue(resp.getWriter(), resultMap);
        } catch (IOException | SQLException e) {
            e.printStackTrace();
            try {
                Map<String, Object> errorMap = new HashMap<>();
                errorMap.put("code", 500);
                errorMap.put("msg", "查询排行榜过程中出现错误");
                errorMap.put("data", null);
                mapper.writeValue(resp.getWriter(), errorMap);
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

    /**
     * @desc  教师端课程查询
     * @param req
     * @param resp
     */
    private void tquery(HttpServletRequest req, HttpServletResponse resp) {
        try {
            // 从Session中获取教师id
            String tid = TokenUtil.getId(req);

            // 检查是否成功从Session获取到tid，如果未获取到，返回错误信息
            if (tid == null) {
                Map<String, Object> map = new HashMap<>();
                map.put("code", 201);
                map.put("msg", "未能从Session中获取到教师id，请检查相关设置");
                map.put("data", null);
                mapper.writeValue(resp.getWriter(), map);
                return;
            }
            // 执行查询
            List<Map<String, Object>> queryResult = service.tqueryById(tid);
            Map<String, Object> map = new HashMap<>();
            map.put("code", 200);
            map.put("msg", "查询成功");
            map.put("data", queryResult);
            mapper.writeValue(resp.getWriter(), map);
        } catch (IOException e) {
            e.printStackTrace();
            try {
                Map<String, Object> map = new HashMap<>();
                map.put("code", 500);
                map.put("msg", "查询过程中出现错误");
                map.put("data", null);
                mapper.writeValue(resp.getWriter(), map);
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * @desc  课程的结构化查询
     * @param req
     * @param resp
     * @throws SQLException
     * @throws IOException
     */
    private void structurequery(HttpServletRequest req, HttpServletResponse resp) throws SQLException, IOException {
        String condition = req.getParameter("condition");
        List<Direction> directions = service.structurequery(condition, 12, pageno);
        Map<String, Object> map = new HashMap<>();
                 map.put("code", 200);
                 map.put("msg", "结构化查询成功");
                 map.put("data", directions);
                 mapper.writeValue(resp.getWriter(), map);
    }

    /**
     * @desc  查询课程信息
     * @param req
     * @param resp
     * @throws SQLException
     * @throws IOException
     */
    @Override
    public void query(HttpServletRequest req, HttpServletResponse resp) throws SQLException, IOException {
        String condition = req.getParameter("condition");
        List<Courses> courses = service.queryAll(condition,10, pageno);
        Map<String, Object> map = new HashMap<>();
                 map.put("code", 200);
                 map.put("msg", "查询成功");
                 map.put("data", courses);
                 mapper.writeValue(resp.getWriter(), map);
    }

    @Override
    public void delete(HttpServletRequest req, HttpServletResponse resp) throws SQLException, IOException {
        String id = req.getParameter("id");
        service.deleteById(id);
         Map<String, Object> map = new HashMap<>();
                 map.put("code", 200);
                 map.put("msg", "删除成功");
                 map.put("data", id);
                 mapper.writeValue(resp.getWriter(), map);
    }

    @Override
    public void queryOne(HttpServletRequest req, HttpServletResponse resp) throws SQLException, IOException {
        String id = req.getParameter("id");
        Courses courses = service.queryOneForId(id);
        Map<String, Object> map = new HashMap<>();
                 map.put("code", 200);
                 map.put("msg", "查询成功");
                 map.put("data", courses);
                 mapper.writeValue(resp.getWriter(), map);
    }

    @Override
    public void edit(HttpServletRequest req, HttpServletResponse resp) throws SQLException, IOException {
        String id = req.getParameter("id");
        String tid = req.getParameter("tid");
        String level = req.getParameter("level");
        String name = req.getParameter("name");
        String introduce = req.getParameter("introduce");
        String price = req.getParameter("price");
        String direction = req.getParameter("direction");
        String subject = req.getParameter("subject");
        service.update(id, tid, level, name, introduce, price, direction, subject);
         Map<String, Object> map = new HashMap<>();
                 map.put("code", 200);
                 map.put("msg", "修改成功");
                 map.put("data", id+":"+name);
                 mapper.writeValue(resp.getWriter(), map);
    }

    /**
     * @desc  课程信息的添加
     * @param req
     * @param resp
     * @throws SQLException
     * @throws IOException
     */
    @Override
    public void add(HttpServletRequest req, HttpServletResponse resp) throws SQLException, IOException {
        String id = IdUtil.simpleUUID();

        String tid = TokenUtil.getId(req);

        String level = req.getParameter("clevel");
        String name = req.getParameter("cname");
        String introduce = req.getParameter("cintroduce");
        String price = req.getParameter("cprice");
        String direction = req.getParameter("cdirection");
        String subject = req.getParameter("csubject");

        String url = doUrl(req, resp);

      //检查tid是否成功从Session获取到，如果未获取到，可以根据业务需求进行相应处理，这里简单返回错误信息
        if (tid == null) {
            Map<String, Object> map = new HashMap<>();
            map.put("code", 201);
            map.put("msg", "未能从Session中获取到tid，请检查相关设置");
            map.put("data", null);
            mapper.writeValue(resp.getWriter(), map);
            return;
        }
         service.add(id, tid, url, 0, level, name, introduce, price, direction, subject,0,1);
         Map<String, Object> map = new HashMap<>();
                 map.put("code", 200);
                 map.put("msg", "添加成功");
                 map.put("data", name);
                 mapper.writeValue(resp.getWriter(), map);
    }


    public static String doUrl(HttpServletRequest request, HttpServletResponse response) throws  IOException {
        String url = "";
        {
            System.out.println(request.getParameter("id"));
            // 检测是否为多媒体上传
            if (!ServletFileUpload.isMultipartContent(request)) {
                // 如果不是则停止
                PrintWriter writer = response.getWriter();
                writer.println("Error: 表单必须包含 enctype=multipart/form-data");
                writer.flush();
                return null;
            }

            // 配置上传参数
            DiskFileItemFactory factory = new DiskFileItemFactory();
            // 设置内存临界值 - 超过后将产生临时文件并存储于临时目录中
            factory.setSizeThreshold(MEMORY_THRESHOLD);
            // 设置临时存储目录
            factory.setRepository(new File(System.getProperty("java.io.tmpdir")));

            ServletFileUpload upload = new ServletFileUpload(factory);

            // 设置最大文件上传值
            upload.setFileSizeMax(MAX_FILE_SIZE);

            // 设置最大请求值 (包含文件和表单数据)
            upload.setSizeMax(MAX_REQUEST_SIZE);

            // 中文处理
            upload.setHeaderEncoding("UTF-8");

            try {
                // 解析请求的内容提取文件数据
                @SuppressWarnings("unchecked")
                List<FileItem> formItems = upload.parseRequest(request);

                if (formItems!= null && formItems.size() > 0) {
                    // 迭代表单数据
                    for (FileItem item : formItems) {
                        // 处理不在表单中的字段
                        if (!item.isFormField()) {
                            // 上传文件到七牛云并获取返回的URL
                            url = qiNiuUploadUtils.uploadFiles(item.getInputStream(), item.getName());

                            if (url!= null) {
                                // 创建一个Map来存储要返回给前端的信息
                                Map<String, Object> resultMap = new HashMap<>();
                                resultMap.put("status", "success");
                                resultMap.put("message", "上传成功");
                                resultMap.put("url", url);


                                // 将Map转换为JSON格式并返回给前端
                                ObjectMapper mapper = new ObjectMapper();
                                mapper.writeValue(response.getWriter(), resultMap);
                            } else {
                                Map<String, Object> resultMap = new HashMap<>();
                                resultMap.put("status", "failure");
                                resultMap.put("message", "上传失败");

                                ObjectMapper mapper = new ObjectMapper();
                                mapper.writeValue(response.getWriter(), resultMap);
                            }
                        }
                    }
                }
            } catch (Exception ex) {
                // 处理上传过程中出现的异常情况
                request.setAttribute("message", "错误信息: " + ex.getMessage());

                Map<String, Object> resultMap = new HashMap<>();
                resultMap.put("status", "failure");
                resultMap.put("message", "上传过程中出现错误");

                ObjectMapper mapper = new ObjectMapper();
                mapper.writeValue(response.getWriter(), resultMap);
            }
        }
        return url;
    }
}
